//
//  MyPopover.m
//  sandbox
//
//  Created by 杨岑 on 1/7/15.
//  Copyright (c) 2015 杨岑. All rights reserved.
//

#import "MyPopover.h"
#import "MyPopoverWindow.h"
#import "MyPopoverView.h"
#import "MyPopoverHandleView.h"
#import "MyPopoverWindowController.h"


@implementation MyPopover
{
    MyPopoverWindow* _window;
    MyPopoverView* _view;
    MyPopoverHandleView* _handleView;
    MyPopoverWindowController* _windowController;
}

+ (instancetype)createWith:(NSViewController *)vc
{
    return [[MyPopover alloc] initWith:vc];
}

- (instancetype)init
{
    self = [super init];
    if (self)
    {
        //_windowController = [[MyPopoverWindowController alloc] initWithWindowNibName:@"MyPopoverWindow"];
        _properties = [[MyPopoverProperties alloc] init];
        _windowController.properties = _properties;
        _window = [[MyPopoverWindow alloc] initWithContentRect:NSMakeRect(0, 0, 0, 0) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO];
        _view = [[MyPopoverView alloc] init];
        _window.isVisible = NO;
        _handleView = [[MyPopoverHandleView alloc] init];
        [_window.contentView addSubview:_view];
        [_window.contentView addSubview:_handleView];
        _windowController = [[MyPopoverWindowController alloc] initWithWindow:_window];
    }
    return self;
}

- (instancetype)initWith:(NSViewController*)vc
{
    self = [self init];
    if (self)
    {
        self.contentViewController = vc;
    }
    return self;
}

- (void)popAt:(NSPoint)hotspot preferredPosition:(char)position
{
    [self popAround:NSMakeRect(hotspot.x, hotspot.x, 1, 1) preferredPosition:position];
}

- (CGFloat)CGSizeArea:(CGSize)size
{
    return size.width * size.height;
}

- (void)popAround:(NSRect)hotspotRect preferredPosition:(char)position
{
    NSRect screenRect = [NSScreen mainScreen].frame;
    NSRect viewContentRect = self.contentViewController.view.bounds;
    NSRect popoverRect;
    NSRect rectOnLeft, rectOnRight;
    NSRect rectOnTop, rectOnBottom;
    
    rectOnLeft.size.width = viewContentRect.size.width + _windowController.handleWidth;
    rectOnLeft.size.height = viewContentRect.size.height;
    rectOnLeft.origin.x = hotspotRect.origin.x - rectOnLeft.size.width,
    rectOnLeft.origin.y = (screenRect.size.height - viewContentRect.size.height) / 2;

    rectOnRight.size.width = viewContentRect.size.width + _windowController.handleWidth;
    rectOnRight.size.height = viewContentRect.size.height;
    rectOnRight.origin.x = hotspotRect.origin.x + hotspotRect.size.width,
    rectOnRight.origin.y = (screenRect.size.height - viewContentRect.size.height) / 2;

    rectOnTop.size.width = viewContentRect.size.width;
    rectOnTop.size.height = viewContentRect.size.height + _windowController.handleWidth;
    rectOnTop.origin.x = hotspotRect.origin.x + hotspotRect.size.width / 2,
    rectOnTop.origin.y = hotspotRect.origin.y + hotspotRect.size.height;

    rectOnBottom.size.width = viewContentRect.size.width;
    rectOnBottom.size.height = viewContentRect.size.height + _windowController.handleWidth;
    rectOnBottom.origin.x = hotspotRect.origin.x + hotspotRect.size.width / 2,
    rectOnBottom.origin.y = hotspotRect.origin.y - rectOnBottom.size.height;
    
    NSRect rectMaxIntersectionWithScreen;
    NSRect* rects[] = {&rectOnLeft, &rectOnRight, &rectOnTop, &rectOnBottom};
    for (int i = 0; i < 4; i++)
    {
        NSRect* pRect = rects[i];
        NSRect rectIntersection = NSIntersectionRect(*pRect, screenRect);
        if ([self CGSizeArea:rectMaxIntersectionWithScreen.size] < [self CGSizeArea:rectIntersection.size])
        {
            rectMaxIntersectionWithScreen = rectIntersection;
        }
    }
    
    switch (position)
    {
        case 'l':
        case 'L':
            popoverRect = rectOnLeft;
            if (!NSContainsRect(screenRect, popoverRect))
            {
                if (NSContainsRect(screenRect, rectOnRight))
                {
                    popoverRect = rectOnLeft;
                }
                else if (NSContainsRect(screenRect, rectOnTop))
                {
                    popoverRect = rectOnLeft;
                }
                else if (NSContainsRect(screenRect, rectOnBottom))
                {
                    popoverRect = rectOnLeft;
                }
                else
                {
                    popoverRect = rectMaxIntersectionWithScreen;
                }
            }
            break;
        case 'r':
        case 'R':
            popoverRect = rectOnRight;
            if (!NSContainsRect(screenRect, popoverRect))
            {
                if (NSContainsRect(screenRect, rectOnLeft))
                {
                    popoverRect = rectOnLeft;
                }
                else if (NSContainsRect(screenRect, rectOnTop))
                {
                    popoverRect = rectOnLeft;
                }
                else if (NSContainsRect(screenRect, rectOnBottom))
                {
                    popoverRect = rectOnLeft;
                }
                else
                {
                    popoverRect = rectMaxIntersectionWithScreen;
                }
            }
            break;
            
        case 't':
        case 'T':
            popoverRect = rectOnTop;
            if (!NSContainsRect(screenRect, popoverRect))
            {
                if (NSContainsRect(screenRect, rectOnBottom))
                {
                    popoverRect = rectOnLeft;
                }
                else if (NSContainsRect(screenRect, rectOnRight))
                {
                    popoverRect = rectOnLeft;
                }
                else if (NSContainsRect(screenRect, rectOnLeft))
                {
                    popoverRect = rectOnLeft;
                }
                else
                {
                    popoverRect = rectMaxIntersectionWithScreen;
                }
            }
            break;
        case 'b':
        case 'B':
            popoverRect = rectOnBottom;
            if (!NSContainsRect(screenRect, popoverRect))
            {
                if (NSContainsRect(screenRect, rectOnTop))
                {
                    popoverRect = rectOnLeft;
                }
                else if (NSContainsRect(screenRect, rectOnRight))
                {
                    popoverRect = rectOnLeft;
                }
                else if (NSContainsRect(screenRect, rectOnLeft))
                {
                    popoverRect = rectOnLeft;
                }
                else
                {
                    popoverRect = rectMaxIntersectionWithScreen;
                }
            }
            break;
    }
    
    NSViewAnimation* anim;
    NSArray* animations;
    switch (_animation) {
        case MyPopoverAnimationPop:
        {
            NSValue* startFrame = [NSValue valueWithRect:NSMakeRect(0, 0, 1, 1)];
            NSValue* endFrame = [NSValue valueWithRect:NSInsetRect(_window.frame, 15, 15)];
            NSValue* originalFrame = [NSValue valueWithRect:_window.frame];
            NSDictionary* pop1 = @{NSViewAnimationTargetKey: _window,
                                   NSViewAnimationStartFrameKey: startFrame,
                                       NSViewAnimationEndFrameKey: endFrame};
            NSDictionary* pop2 = @{NSViewAnimationTargetKey: _window,
                                   NSViewAnimationStartFrameKey: endFrame,
                                   NSViewAnimationEndFrameKey: originalFrame};
            animations = @[pop1, pop2];
            [_window setFrame:startFrame.rectValue display:NO];
        }
            break;
            
        default:
        {
            NSDictionary* fadeInProps = @{NSViewAnimationTargetKey: _window,
                                          NSViewAnimationEffectKey: NSViewAnimationFadeInEffect};
            animations = @[fadeInProps];
        }
            break;
    }
    
    anim = [[NSViewAnimation alloc] initWithViewAnimations:animations];
    anim.delegate = self;
    anim.duration = self.animationDuration;
    anim.animationBlockingMode = NSAnimationBlocking;
    anim.animationCurve = NSAnimationEaseOut;
    [anim startAnimation];
}

- (BOOL)animationShouldStart:(NSAnimation *)animation
{
    _window.isVisible = YES;
    return YES;
}

- (void)animationDidEnd:(NSAnimation *)animation
{
    _window.isVisible = NO;
    _window.alphaValue = 1.0;
}

- (void)animationDidStop:(NSAnimation *)animation
{
    _window.isVisible = NO;
    _window.alphaValue = 1.0;
}

@end
